package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.help.ProUpdateHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.InvoiceErrorCodeEnum;
import com.xbongbong.pro.invoice.pojo.InvoiceCommonSavePojo;
import com.xbongbong.pro.invoice.pojo.InvoiceRelationshipEditPojo;
import com.xbongbong.pro.invoice.pojo.RefTypePojo;
import com.xbongbong.pro.message.constant.InvoicePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.PurchaseInvoiceRelationshipEntity;
import com.xbongbong.saas.domain.entity.ext.PurchaseInvoiceEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.business.RefTypeEnum;
import com.xbongbong.saas.model.PurchaseInvoiceRelationshipModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
@Slf4j
public class PurchaseInvoiceHelp {

    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private ProUpdateHelp proUpdateHelp;
    @Resource
    private PurchaseInvoiceRelationshipModel purchaseInvoiceRelationshipModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private MessageService messageService;

    /** 建立发票关系
     *
     * @param isEnable     是否审批
     * @param purchaseInvoiceId    发票id
     * @param now          时间
     * @param supplierId   客户id
     * @param supplierName 客户名称
     * @param corpid       公司id
     * @param money        金额
     * @param purchaseId   合同id
     * @param purchaseNo   合同编号
     * @param payPlanId    回款id
     * @param payPlanNo    回款编号
     * @param type         类性
     * @throws XbbException 异常
     */
    public PurchaseInvoiceRelationshipEntity buildNewInvoiceRelation(boolean isEnable, Long purchaseInvoiceId, Long now, Long supplierId, String supplierName, String corpid, Double money, Long purchaseId, String purchaseNo, Long payPlanId, String payPlanNo, Long paySheetId, String paySheetNo, Integer type) throws XbbException {
        PurchaseInvoiceRelationshipEntity purchaseInvoiceRelationshipEntity = new PurchaseInvoiceRelationshipEntity();
        purchaseInvoiceRelationshipEntity.setPurchaseInvoiceId(purchaseInvoiceId);
        purchaseInvoiceRelationshipEntity.setAddTime(now);
        purchaseInvoiceRelationshipEntity.setUpdateTime(now);
        purchaseInvoiceRelationshipEntity.setSupplierId(supplierId);
        purchaseInvoiceRelationshipEntity.setSupplierName(supplierName);
        purchaseInvoiceRelationshipEntity.setCorpid(corpid);
        purchaseInvoiceRelationshipEntity.setIsCancel(BasicConstant.ZERO);
        purchaseInvoiceRelationshipEntity.setDel(DelEnum.NORMAL.getDel());
        purchaseInvoiceRelationshipEntity.setMoney(money);
        purchaseInvoiceRelationshipEntity.setPurchaseId(purchaseId);
        purchaseInvoiceRelationshipEntity.setPurchaseNo(purchaseNo);
        purchaseInvoiceRelationshipEntity.setPurchaseName("");
        purchaseInvoiceRelationshipEntity.setPayPlanId(payPlanId);
        purchaseInvoiceRelationshipEntity.setPayPlanNo(payPlanNo);
        purchaseInvoiceRelationshipEntity.setPaySheetId(paySheetId);
        purchaseInvoiceRelationshipEntity.setPaySheetNo(paySheetNo);
        if (isEnable) {
            purchaseInvoiceRelationshipEntity.setFlowStatus(FlowStatusEnum.APPROVAL_PENDING.getType());
        } else {
            purchaseInvoiceRelationshipEntity.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
        }
        purchaseInvoiceRelationshipEntity.setType(type);
        return purchaseInvoiceRelationshipEntity;
    }

    /**
     * 发票编辑时新增删除数据
     *  老的数据减去新的数据得到删除的关联数据,新的减去老的得到新增的关联数据
     * @param newData
     * @param oldData
     * @param corpid
     * @param invoiceId
     * @return
     * @throws XbbException
     */
    public InvoiceRelationshipEditPojo getAddOrDeleteRelationship(JSONObject newData, JSONObject oldData, String corpid, Long invoiceId)throws XbbException{
        // 老的
        List<Long> oldPayPlanIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(oldData, PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(), new JSONArray()).toJavaList(Long.class);
        List<Long> oldPurchaseIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(oldData, PurchaseInvoiceEnum.PURCHASE_ID.getAttr(), new JSONArray()).toJavaList(Long.class);
        //回款单的
        List<Long> oldPaySheetIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(oldData,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(),new JSONArray()).toJavaList(Long.class);
        // 新的
        List<Long> payPlanIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(newData, PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(), new JSONArray()).toJavaList(Long.class);
        List<Long> purchaseIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(newData,PurchaseInvoiceEnum.PURCHASE_ID.getAttr(), new JSONArray()).toJavaList(Long.class);
        //回款单的
        List<Long> paySheetIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(newData,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(), new JSONArray()).toJavaList(Long.class);

        oldPayPlanIdList.removeAll(payPlanIdList);
        oldPurchaseIdList.removeAll(purchaseIdList);
        oldPaySheetIdList.removeAll(paySheetIdList);
        //删掉减去的，并更新到对应的关联数据里
        invoiceEditAmountCompute(corpid,invoiceId,oldPayPlanIdList, RefTypeEnum.PAYPLAN);
        invoiceEditAmountCompute(corpid,invoiceId,oldPurchaseIdList,RefTypeEnum.PURCHASE);
        invoiceEditAmountCompute(corpid,invoiceId,oldPaySheetIdList,RefTypeEnum.PAYSHEET);
        InvoiceRelationshipEditPojo invoiceRelationshipEditPojo = new InvoiceRelationshipEditPojo();
        invoiceRelationshipEditPojo.setOldPurchaseIdList(oldPurchaseIdList);
        invoiceRelationshipEditPojo.setPurchaseIdList(purchaseIdList);
        invoiceRelationshipEditPojo.setOldPayPlanIdList(oldPayPlanIdList);
        invoiceRelationshipEditPojo.setPayPlanIdList(payPlanIdList);
        invoiceRelationshipEditPojo.setOldPaySheetIdList(oldPaySheetIdList);
        invoiceRelationshipEditPojo.setPaySheetIdList(paySheetIdList);
        return invoiceRelationshipEditPojo;
    }


    /**
     * 发票编辑的时候老发票如果被删除可以先进行累加在从发票金额上减去
     * @param corpid 公司编号
     * @param invoiceId 发票id
     * @param idList 关联id 集合
     * @param refTypeEnum 关联的枚举类型
     * @throws XbbException
     */
    private void invoiceEditAmountCompute(String corpid,Long invoiceId,List<Long> idList,RefTypeEnum refTypeEnum) throws XbbException{
        if(CollectionsUtil.isEmpty(idList)){
            return;
        }
        RefTypePojo refTypePojo = getRefType(refTypeEnum);
        PurchaseInvoiceEnum purchaseInvoiceEnum = refTypePojo.getPurchaseInvoiceEnum();
        Integer businessType = refTypePojo.getBusinessType();
        String attr = refTypePojo.getInvoiceAmountAttr();
        Map<Long, PaasFormDataEntityExt> purchaseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //除这次发票之外其它发票关联了这些关系的发票关系map
        Map<Long, List<PurchaseInvoiceRelationshipEntity>> oldInvoiceMap = getInvoiceMap(corpid, invoiceId, idList,purchaseInvoiceEnum);
        if(Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode())){
            List<PaasFormDataEntityExt> contractList = paasEsModel.getByIdList(idList, corpid, SaasMarkEnum.SAAS.getCode(), businessType, new ArrayList<>(), IndexTypeEnum.IDX_SAAS_PURCHASE);
            contractList.forEach(contract-> purchaseMap.put(contract.getId(), contract));
        }
        for (Long id : idList) {
            List<PurchaseInvoiceRelationshipEntity>  singleRelationInvoiceList = oldInvoiceMap.get(id);
            Double otherInvoiceSumAmount = 0D;
            if (CollectionsUtil.isNotEmpty(singleRelationInvoiceList)) {
                for (PurchaseInvoiceRelationshipEntity purchaseInvoiceRelationshipEntity : singleRelationInvoiceList) {
                    otherInvoiceSumAmount = Arith.add(otherInvoiceSumAmount,purchaseInvoiceRelationshipEntity.getMoney());
                }
            }
            if(Objects.equals(businessType,XbbRefTypeEnum.PURCHASE.getCode())) {
                JSONObject jsonObject = new JSONObject();
                if (Objects.nonNull(purchaseMap.get(id))) {
                    jsonObject.put(PurchaseEnum.INVOICE_AMOUNT.getAttr(), otherInvoiceSumAmount);
                    Double amount = purchaseMap.get(id).getData().getDouble(ContractEnum.AMOUNT.getAttr());
                    jsonObject.put(PurchaseEnum.UN_INVOICE_AMOUNT.getAttr(), amount - otherInvoiceSumAmount);
                    proUpdateHelp.update(businessType, corpid, id, jsonObject);
                }
            }else {
                proUpdateHelp.update(businessType, corpid, id, attr, otherInvoiceSumAmount);
            }
        }
    }

    /**
     * 获取发票的关联类型pojo
     * @param refTypeEnum
     * @return
     * @throws XbbException
     */
    private RefTypePojo getRefType(RefTypeEnum refTypeEnum) throws XbbException{
        RefTypePojo refTypePojo = new RefTypePojo();
        switch (refTypeEnum){
            case PURCHASE:
                refTypePojo.setBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                refTypePojo.setPurchaseInvoiceEnum(PurchaseInvoiceEnum.PURCHASE_ID);
                refTypePojo.setInvoiceAmountAttr(PurchaseEnum.INVOICE_AMOUNT.getAttr());
                refTypePojo.setAmountAttr(PurchaseEnum.TOTAL_MONEY.getAttr());
                break;
            case PAYPLAN:
                refTypePojo.setBusinessType(XbbRefTypeEnum.PAY_PLAN.getCode());
                refTypePojo.setPurchaseInvoiceEnum(PurchaseInvoiceEnum.PAY_PLAN_ID);
                refTypePojo.setInvoiceAmountAttr(PayPlanEnum.INVOICE_AMOUNT.getAttr());
                refTypePojo.setAmountAttr(PayPlanEnum.AMOUNT.getAttr());
                break;
            case PAYSHEET:
                refTypePojo.setBusinessType(XbbRefTypeEnum.PAY_SHEET.getCode());
                refTypePojo.setPurchaseInvoiceEnum(PurchaseInvoiceEnum.PAY_SHEET_ID);
                refTypePojo.setInvoiceAmountAttr(PaySheetEnum.INVOICE_AMOUNT.getAttr());
                refTypePojo.setAmountAttr(PaySheetEnum.AMOUNT.getAttr());
                break;
            default:
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216021);
        }
        return refTypePojo;
    }

    /**
     * 根据采购合同id/付款计划id/付款单id 放入一个map 对应的值为开票的关联实体
     * @param corpid
     * @param invoiceId
     * @param oldRelationIdList
     * @param purchaseInvoiceEnum
     * @return
     * @throws XbbException
     */
    public Map<Long, List<PurchaseInvoiceRelationshipEntity>> getInvoiceMap(String corpid, Long invoiceId, List<Long> oldRelationIdList,PurchaseInvoiceEnum purchaseInvoiceEnum) throws XbbException {
        Map<Long, List<PurchaseInvoiceRelationshipEntity>> oldInvoiceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<PurchaseInvoiceRelationshipEntity> relationList = getRelationShipInvoice(invoiceId, corpid, oldRelationIdList,purchaseInvoiceEnum);
        relationList.forEach(relation -> {
            Long relationId = 0L;
            if (Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PURCHASE_ID)) {
                relationId = relation.getPurchaseId();
            } else if (Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PAY_PLAN_ID)) {
                relationId = relation.getPayPlanId();
            }else if(Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PAY_SHEET_ID)){
                relationId = relation.getPaySheetId();
            }
            List<PurchaseInvoiceRelationshipEntity> list = new ArrayList<>();
            if (oldInvoiceMap.containsKey(relationId)) {
                list = oldInvoiceMap.get(relationId);
            }
            list.add(relation);
            oldInvoiceMap.put(relationId, list);
        });
        return oldInvoiceMap;
    }

    public List<PurchaseInvoiceRelationshipEntity> getRelationShipInvoice(Long purchaseInvoiceId, String corpid, List<Long> relationIdList,PurchaseInvoiceEnum purchaseInvoiceEnum) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.IS_CANCEL, 0);
        param.put("purchaseInvoiceIdNot", purchaseInvoiceId);
        if (Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PURCHASE_ID)) {
            param.put("purchaseIdIn", relationIdList);
        } else if (Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PAY_PLAN_ID)) {
            param.put("payPlanIdIn", relationIdList);
        } else if(Objects.equals(purchaseInvoiceEnum,PurchaseInvoiceEnum.PAY_SHEET_ID)){
            param.put("paySheetIdIn",relationIdList);
        }
        return purchaseInvoiceRelationshipModel.findEntitys(param);
    }

    public void purchaseInvoiceMessagePushHandle(InvoiceCommonSavePojo invoiceCommonSavePojo) throws XbbException{
        PaasFormDataEntity newPaasFormDataEntity = invoiceCommonSavePojo.getEntityExt();
        String creatorId = newPaasFormDataEntity.getCreatorId();
        String corpid = invoiceCommonSavePojo.getCorpid();
        boolean isNew = invoiceCommonSavePojo.getIsNew();
        Long originId = invoiceCommonSavePojo.getOriginId();
        Long invoiceId = invoiceCommonSavePojo.getInvoiceId();
        Integer isImport = invoiceCommonSavePojo.getIsImport();
        Integer businessType = invoiceCommonSavePojo.getBusinessType();
        Integer subBusinessType = invoiceCommonSavePojo.getSubBusinessType();
        UserEntity creatorUser = userModel.getByKeyIngoreDel(creatorId, corpid);
        if(isNew) {
            if (originId > BasicConstant.ZERO) {
                if (!Objects.equals(isImport, 1)) {
                    // 红冲发票创建消息推送
                    PurchaseInvoiceEntityExt purchaseInvoiceEntityExt = new PurchaseInvoiceEntityExt();
                    BeanUtil.copyProperties(newPaasFormDataEntity, purchaseInvoiceEntityExt);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.PURCHASE_INVOICE_RED_ADD_PUSH.getCode(), PushTypeEnum.PURCHASE_INVOICE_RED_ADD_PUSH.getSubCode(), invoiceCommonSavePojo.getLoginUser(), purchaseInvoiceEntityExt);
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(purchaseInvoiceEntityExt.getAppId(), purchaseInvoiceEntityExt.getMenuId(), purchaseInvoiceEntityExt.getFormId(), invoiceId, Collections.singletonList(invoiceId), SaasMarkEnum.SAAS.getCode(), businessType, subBusinessType);
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(invoiceId), 0, null, I18nMessageUtil.getMessage(InvoicePushConstant.PURCHASE_INVOICE_RED_ADD_TITLE), String.format(I18nMessageUtil.getMessage(InvoicePushConstant.PURCHASE_INVOICE_RED_ADD_CONTENT), creatorUser.getName(), purchaseInvoiceEntityExt.getSerialNo()), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.PURCHASE_INVOICE_RED_ADD_PUSH);
                }
            } else {
                if (!Objects.equals(isImport, 1)) {
                    // 发票创建消息推送
                    PurchaseInvoiceEntityExt purchaseInvoiceEntityExt = new PurchaseInvoiceEntityExt();
                    BeanUtil.copyProperties(newPaasFormDataEntity, purchaseInvoiceEntityExt);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.PURCHASE_INVOICE_ADD_PUSH.getCode(), PushTypeEnum.PURCHASE_INVOICE_ADD_PUSH.getSubCode(), invoiceCommonSavePojo.getLoginUser(), purchaseInvoiceEntityExt);
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(purchaseInvoiceEntityExt.getAppId(), purchaseInvoiceEntityExt.getMenuId(), purchaseInvoiceEntityExt.getFormId(), invoiceId, Collections.singletonList(invoiceId), SaasMarkEnum.SAAS.getCode(), businessType, subBusinessType);
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(invoiceId), 0, null, I18nMessageUtil.getMessage(InvoicePushConstant.PURCHASE_INVOICE_ADD_TITLE), String.format(I18nMessageUtil.getMessage(InvoicePushConstant.PURCHASE_INVOICE_ADD_CONTENT), creatorUser.getName(), newPaasFormDataEntity.getSerialNo()), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.PURCHASE_INVOICE_ADD_PUSH);
                }
            }
        }
    }
}
